/**
 * @author LANG
 * Copyright 2009, QSC.
 * All rights reserved.
 * 
 * because the limit of ps_2_0, we have to seperate the calculate of the ssao into 8 pass, 2 shader;
 */
float4x4 worldViewProjection : WorldViewProjection;

float4x4 viewProjInverse;

float4 lightColor;

sampler positionTex;
sampler normalTex;
sampler randomTex;

float sample_rad;
float intensity;
float scale;
float bias;

float2 vec;

struct VertexShaderInput {
	float4 position : POSITION;
	float2 tex : TEXCOORD0;  // Texture coordinates
};
	
VertexShaderInput vertexShaderFunction(VertexShaderInput input) {
	VertexShaderInput output;

	output.position = mul(input.position, worldViewProjection);
		
	output.tex = input.tex;
	return output;
}
 
float3 getPosition(float2 texcoord)
{
	float4 position= tex2D(positionTex, texcoord);
	position.xy = position.xy * 2 - 1;
	position = mul(float4(position.xyz, 1), viewProjInverse);
	position.xyz /= position.w;
	return position.xyz;
}

float3 getNormal(float2 texcoord)
{
	return normalize(tex2D(normalTex, texcoord).xyz * 2 - 1);
}

float2 getRandom(float2 texcoord)
{
	return normalize(tex2D(randomTex, 1024 / 64 * texcoord).xy * 2 - 1);
}
 
float doAmbientOcclusion(float2 uv, float2 texcoord, float3 pos, float3 normal)
{
	float3 diff = getPosition(texcoord + uv) - pos;
	const float3 v = normalize(diff);
	const float d = length(diff) * scale;
	return max(0, dot(normal, v) - bias)*(1/(1+d))*intensity;
}

float4 pixelShaderFunction(VertexShaderInput input): COLOR {
	input.tex.y = 1 - input.tex.y;
    float3 p = getPosition(input.tex);
    float3 n = getNormal(input.tex);
    float2 rand = getRandom(input.tex);
    float rad = sample_rad / tex2D(positionTex, input.tex).z;
   
    float ao = 0;
    float2 coord1 = reflect(vec,rand)*rad;
    float2 coord2 = reflect(coord1.x*0.707 - coord1.y*0.707, coord1.x*0.707 + coord1.y*0.707);
    
    ao += doAmbientOcclusion(coord2*0.5, input.tex, p, n);
    return ao/16;
}
  
// #o3d VertexShaderEntryPoint vertexShaderFunction
// #o3d PixelShaderEntryPoint pixelShaderFunction
// #o3d MatrixLoadOrder RowMajor